﻿using System.Linq;
using System;
using System.Windows;
using System.Windows.Input;
using CodeCounsel.SharePoint.RibbonDesigner.ViewModel;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Controls;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace CodeCounsel.SharePoint.RibbonDesigner.View.AttachedBehaviors
{
    class VisualFocusManager
        : FrameworkElement
    {
        public static readonly DependencyProperty IsSelectableProperty = 
            DependencyProperty.RegisterAttached("IsSelectable", typeof(bool), typeof(VisualFocusManager), 
                new UIPropertyMetadata(false, IsSelectableChanged));

        public static readonly DependencyProperty FocusVisualStyleProperty = 
            DependencyProperty.RegisterAttached("FocusVisualStyle", typeof(Style), typeof(VisualFocusManager), 
                new UIPropertyMetadata(null));

        public static Style GetFocusVisualStyle(DependencyObject obj)
        {
            return (Style)obj.GetValue(FocusVisualStyleProperty);
        }

        public static void SetFocusVisualStyle(DependencyObject obj, Style value)
        {
            obj.SetValue(FocusVisualStyleProperty, value);
        }

        public static void SetIsSelectable(DependencyObject obj, bool value)
        {
            obj.SetValue(IsSelectableProperty, value);
        }

        static void IsSelectableChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.OldValue == false && (bool)e.NewValue == true)
            {
                Attach(sender);
            }
            else if ((bool)e.OldValue == true && (bool)e.NewValue == false)
            {
                Detach(sender);
            }
        }

        static void Attach(DependencyObject obj)
        {
            FrameworkElement element = (FrameworkElement)obj;
            element.GotFocus += Element_GotFocus;
            element.LostFocus += Element_LostFocus;
            element.FocusVisualStyle = null;
            element.Focusable = true;
            element.MouseDown += (sender, e) => 
            {
                element.Focus();
                e.Handled = true;
            };
        }

        static void Element_GotFocus(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;
            DependencyObject scope = FocusManager.GetFocusScope(element);
            if (FocusManager.GetFocusedElement(scope) == element)
            {
                AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
                layer.Add(new FocusVisualAdorner(element, GetFocusVisualStyle(element)));

                
                //ITrackSelection selectionService = Package.GetGlobalService(typeof(STrackSelection)) as ITrackSelection;
                //System.Collections.ArrayList items = new System.Collections.ArrayList();
                //items.Add(element.DataContext);
                //SelectionContainer container = new SelectionContainer(true, false);
                //container.SelectableObjects = items;
                //container.SelectedObjects = items;
                //selectionService.OnSelectChange(container);
            }
        }

        static void Element_LostFocus(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)sender;
            AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
            if (layer != null)
            {
                Adorner[] adorners = layer.GetAdorners(element);
                if (adorners != null)
                {
                    Adorner adorner = adorners.FirstOrDefault(a => a.GetType() == typeof(FocusVisualAdorner));
                    if (adorner != null)
                    {
                        layer.Remove(adorner);
                    }
                }
            }
        }
       
        static void Detach(DependencyObject obj)
        {
        }
    }
}
